/**
 * Copyright 2011 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.api.adwords.starterkit.settings;

import com.google.api.adwords.starterkit.db.structures.CampaignStructure;
import com.google.api.adwords.starterkit.db.structures.GeoTargetStructure;
import com.google.api.adwords.starterkit.db.structures.LanguageTargetStructure;
import com.google.api.adwords.starterkit.db.structures.NetworkTargetStructure;
import com.google.api.adwords.v201101.cm.BudgetBudgetDeliveryMethod;
import com.google.api.adwords.v201101.cm.BudgetBudgetPeriod;
import com.google.api.adwords.v201101.cm.CampaignStatus;

import org.apache.log4j.Logger;

import java.util.HashSet;

/**
 * The Class CampaignSettings keeps all settings related to Campaigns.
 * 
 * @author rodrigo.f.vale@gmail.com (Rodrigo Vale)
 */
public class CampaignSettings {
  private String defaultEndDay;
  private long defaultBudgetAmount;
  private BudgetBudgetPeriod defaultBudgetPeriod;
  private BudgetBudgetDeliveryMethod deliveryMethod;
  private HashSet<GeoTargetStructure> geoTargetList;
  private HashSet<NetworkTargetStructure> networkTargetList;
  private HashSet<LanguageTargetStructure> languageTargetList;
  private HashSet<String> platformTargetList;
  private CampaignStatus defaultCampaignStatus;
  private boolean autoPauseCampaign;
  private boolean autoCreation;
  private boolean syncStatus;
  private boolean syncBudget;
  private String biddingStrategy;
  private String pricingModel;
  private long bidCeiling;
  private static final Logger log = Logger.getLogger("StarterKit");

  /**
   * Instantiates a new campaign settings.
   * 
   * @param defaultEndDay the default end day
   * @param defaultBudgetAmount the default budget amount
   * @param defaultBudgetPeriod the default budget period
   * @param deliveryMethod the default campaign delivery method
   * @param geoTargetList the geo target list
   * @param networkTargetList the network target list
   * @param languageTargetList the language target list
   * @param platformTargetList the platform target list
   * @param defaultCampaignStatus the default campaign status
   * @param autoPauseCampaign the auto pause campaign
   * @param syncStatus the sync status
   * @param syncBudget the sync budget
   * @param biddingStrategy the bidding strategy
   * @param pricingModel the pricing model
   * @param bidCeiling the bid ceiling
   * @param autoCreation flag that allows starterkit to create new campaigns
   */
  public CampaignSettings(String defaultEndDay, long defaultBudgetAmount,
      BudgetBudgetPeriod defaultBudgetPeriod, 
      BudgetBudgetDeliveryMethod deliveryMethod,
      HashSet<GeoTargetStructure> geoTargetList,
      HashSet<NetworkTargetStructure> networkTargetList,
      HashSet<LanguageTargetStructure> languageTargetList,
      HashSet<String> platformTargetList, CampaignStatus defaultCampaignStatus,
      boolean autoPauseCampaign, boolean syncStatus, boolean syncBudget,
      String biddingStrategy, String pricingModel, long bidCeiling,
      boolean autoCreation) {
    this.defaultEndDay = defaultEndDay;
    this.defaultBudgetAmount = defaultBudgetAmount;
    this.defaultBudgetPeriod = defaultBudgetPeriod;
    this.setDeliveryMethod(deliveryMethod);
    this.geoTargetList = geoTargetList;
    this.networkTargetList = networkTargetList;
    this.languageTargetList = languageTargetList;
    this.platformTargetList = platformTargetList;
    this.defaultCampaignStatus = defaultCampaignStatus;
    this.autoPauseCampaign = autoPauseCampaign;
    this.syncStatus = syncStatus;
    this.syncBudget = syncBudget;
    setBiddingStrategy(biddingStrategy);
    setPricingModel(pricingModel);
    setBidCeiling(bidCeiling);
    this.setAutoCreation(autoCreation);
  }

  public CampaignSettings() {
    this.defaultEndDay = "20360101";
    this.defaultBudgetAmount = 100000000;
    this.defaultBudgetPeriod = defaultBudgetPeriod.DAILY;
    this.setDeliveryMethod(deliveryMethod.STANDARD);
    this.geoTargetList = new HashSet<GeoTargetStructure>();
    this.networkTargetList = new HashSet<NetworkTargetStructure>();
    NetworkTargetStructure networkTargetStructure =
        new NetworkTargetStructure();
    networkTargetStructure.setNetwork("GOOGLE_SEARCH");
    this.networkTargetList.add(networkTargetStructure);
    this.languageTargetList = new HashSet<LanguageTargetStructure>();
    this.platformTargetList = new HashSet<String>();
    this.platformTargetList.add("DESKTOP");
    this.defaultCampaignStatus = CampaignStatus.PAUSED;
    this.autoPauseCampaign = false;
    this.autoCreation = true;
    this.syncStatus = true;
    this.syncBudget = true;
    setBiddingStrategy("ManualCPC");
    setPricingModel("CLICKS");
    setBidCeiling(0);
    this.setAutoCreation(true);
  }

  public void setBiddingStrategy(String biddingStrategy) {
    biddingStrategy = biddingStrategy.toUpperCase();
    CampaignStructure.validateBiddingStrategy(biddingStrategy);
    this.biddingStrategy = biddingStrategy;
    if (biddingStrategy.equals("MANUALCPC")
        || biddingStrategy.equals("MANUALCPM")) {
      this.pricingModel = "";
      this.bidCeiling = 0;
    } else if (biddingStrategy.equals("CONVERSIONOPTIMIZER")) {
      this.bidCeiling = 0;
    } else if (biddingStrategy.equals("BUDGETOPTIMIZER")) {
      this.pricingModel = "";
    }
  }

  public String getBiddingStrategy() {
    return biddingStrategy.toLowerCase();
  }

  public void setStatus(CampaignStatus status) {
    this.defaultCampaignStatus = status;
  }

  public void setStatus(String status) {
    status = status.toUpperCase();
    CampaignStructure.validateStatus(status);
    this.defaultCampaignStatus = CampaignStatus.fromString(status);
  }

  public void setBudget(long budget) {
    this.defaultBudgetAmount = budget;
  }

  public void setNetworkTarget(
      HashSet<NetworkTargetStructure> networkTargetList) {
    this.networkTargetList = networkTargetList;
  }

  public void setLanguageTarget(
      HashSet<LanguageTargetStructure> languageTarget) {
    this.languageTargetList = languageTarget;
  }

  public void setPlatformTarget(HashSet<String> platformTarget) {
    this.platformTargetList = platformTarget;
  }

  public void setGeoTarget(HashSet<GeoTargetStructure> geoTarget) {
    this.geoTargetList = geoTarget;
  }

  /**
   * Sets the can modify status flag. If set to false, StarterKit will not
   * modify the status of a Campaign even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyStatus(boolean syncStatus) {
    this.syncStatus = syncStatus;
  }

  /**
   * Sets the can modify budget flag. If set to false, StarterKit will not
   * modify the budget of a Campaign even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyBudget(boolean syncBudget) {
    this.syncBudget = syncBudget;
  }

  public boolean getCanModifyStatus() {
    return syncStatus;
  }

  public boolean getCanModifyBudget() {
    return syncBudget;
  }

  public boolean getAutoPause() {
    return autoPauseCampaign;
  }

  /**
   * sets the auto pause Campaign flag. This flag controls if Starter Kit can
   * pause Campaigns automatically. An Campaign is paused automatically when it
   * is present at the AdWords system, but the application do not mention it. 
   * See the demos for a better understanding of it or the AutoPause session at 
   * the manual.
   */
  public void setAutoPause(boolean autoPause) {
    autoPauseCampaign = autoPause;
  }

  public String getEndDay() {
    return defaultEndDay.toLowerCase();
  }

  public void setEndDay(String endDay) {
    defaultEndDay = endDay.toLowerCase();
  }

  public long getBudgetAmount() {
    return defaultBudgetAmount;
  }

  public BudgetBudgetPeriod getBudgetPeriod() {
    return defaultBudgetPeriod;
  }

  public void setBudgetPeriod(String budgetPeriod) {
    budgetPeriod = budgetPeriod.toUpperCase();
    CampaignStructure.validateBudgetPeriod(budgetPeriod);
    defaultBudgetPeriod = BudgetBudgetPeriod.fromString(budgetPeriod);
  }
  
  public void setBudgetPeriod(BudgetBudgetPeriod budgetPeriod) {
    defaultBudgetPeriod = budgetPeriod;
  }

  public CampaignStatus getStatus() {
    return defaultCampaignStatus;
  }

  public HashSet<GeoTargetStructure> getGeoTargetList() {
    return geoTargetList;
  }

  public HashSet<NetworkTargetStructure> getNetworkTargetList() {
    return networkTargetList;
  }

  public HashSet<LanguageTargetStructure> getLanguageTargetList() {
    return languageTargetList;
  }

  public HashSet<String> getPlatformTargetList() {
    return platformTargetList;
  }

  public void setPricingModel(String pricingModel) {
    CampaignStructure.validatePricingModel(pricingModel);
    if (biddingStrategy.equals("conversionoptimizer")) {
      this.pricingModel = pricingModel;
    } else {
      this.pricingModel = "";
      log.info("Can't set PricingModel on a " + biddingStrategy + " strategy");
    }
  }

  public String getPricingModel() {
    return pricingModel.toLowerCase();
  }

  public void setBidCeiling(long bidCeiling) {
    if (biddingStrategy.equals("budgetoptimizer")) {
      this.bidCeiling = bidCeiling;
    } else {
      this.bidCeiling = 0;
      log.info("Can't set bidCeiling on a " + biddingStrategy + " strategy");
    }
  }

  public long getBidCeiling() {
    return bidCeiling;
  }

  /**
   * Sets the auto creation Campaign flag. This flag controls if Starter Kit 
   * can create new Campaigns. Set to false to make sure that
   * the framework will not create any new Campaign even if requested by
   * the application.
   */
  public void setAutoCreation(boolean autoCreation) {
    this.autoCreation = autoCreation;
    if (autoCreation == false) {
      log.info("AutoCreation was set to false. Make sure that your AdWords "
          + "account already have the campaigns and adgroups to be " 
          + "manipulated");
    }
  }

  public boolean getAutoCreation() {
    return autoCreation;
  }

  public void setDeliveryMethod(String deliveryMethod) {
    CampaignStructure.validateDeliveryMethod(deliveryMethod);
    this.deliveryMethod = BudgetBudgetDeliveryMethod.fromString(deliveryMethod);
  }  
  
  public void setDeliveryMethod(BudgetBudgetDeliveryMethod deliveryMethod) {
    this.deliveryMethod = deliveryMethod;
  }  

  public BudgetBudgetDeliveryMethod getDeliveryMethod() {
    return deliveryMethod;
  }
}